namespace Org.Loon.Framework.Xna.Game.Action.Sprite.Effect
{
    using Org.Loon.Framework.Xna.Game.Core;
    using Org.Loon.Framework.Xna.Game.Utils;
    using Org.Loon.Framework.Xna.Game.Core.Graphics.OpenGL;

    public class TriangleEffect
    {

        private int height;

        private float[][] delta;

        private float[] pos;

        private float[] move;

        private float[] avg;

        private float vector;

        private float v_speed;

        public TriangleEffect(float[][] res, float[] ad1, float x, float y,
                float speed)
            : this(res, x, y, speed)
        {

            this.SetAverage(ad1);
        }

        public TriangleEffect(float[][] res, float x, float y, float speed)
        {
            this.SetDelta(res);
            this.v_speed = speed;
            this.pos = new float[2];
            this.move = new float[2];
            this.move[0] = x;
            this.move[1] = y;
            this.ResetAverage();
            this.height = LSystem.screenRect.height;
        }

        public void SetDelta(float[][] res)
        {
            this.delta = res;
        }

        public float[][] GetDelta()
        {
            return delta;
        }

        public void SetAverage(float[] res)
        {
            this.avg = res;
        }

        public void ResetAverage()
        {
            this.avg = new float[2];
            for (int j = 0; j < delta.Length; j++)
            {
                for (int i = 0; i < avg.Length; i++)
                {
                    avg[i] += delta[j][i];
                }
            }
            for (int i = 0; i < avg.Length; i++)
            {
                avg[i] /= 3f;
            }
        }

        public void SetPosX(float x)
        {
            this.pos[0] = x;
        }

        public void SetPosY(float y)
        {
            this.pos[1] = y;
        }

        public void SetPos(float x, float y)
        {
            this.SetPosX(x);
            this.SetPosY(y);
        }

        public float GetPosX()
        {
            return pos[0];
        }

        public float GetPosY()
        {
            return pos[1];
        }

        public void SetVector(float v)
        {
            this.vector = v;
        }

        public void SetVectorSpeed(float v)
        {
            this.v_speed = v;
        }

        public void SetMoveX(float x)
        {
            this.move[0] = x;
        }

        public void SetMoveY(float y)
        {
            this.move[1] = y;
        }

        public void SetMove(int x, int y)
        {
            SetMoveX(x);
            SetMoveY(y);
        }

        public void Next()
        {
            pos[0] += move[0];
            pos[1] += move[1];
            vector += v_speed;
            vector %= 360f;
            if (vector < 0.0f)
            {
                vector += 360f;
            }
        }

        public float[][] Drawing(float x, float y)
        {
            float[][] location = (float[][])CollectionUtils.XNA_CreateJaggedArray(typeof(float), 3, 2);
            for (int i = 0; i < delta.Length; i++)
            {
                float d = GetLine(delta[i][0] - avg[0], delta[i][1] - avg[1]);
                float d1 = GetDegrees(delta[i][0] - avg[0], delta[i][1] - avg[1]);
                float d2 = MathUtils.Cos(MathUtils.ToRadians(vector + d1)) * d
                        + avg[0] + pos[0] + x;
                float d3 = MathUtils.Sin(MathUtils.ToRadians(vector + d1)) * d
                        + avg[1] + pos[1] + y;
                location[i][0] = (d2 + 0.5f);
                location[i][1] = (d3 + 0.5f);
            }
            return location;
        }

        public void Draw(GLEx g)
        {
            Draw(g, 0, 0);
        }

        public void Draw(GLEx g, float x, float y)
        {
            Next();
            float[][] res = Drawing(x, y);
            g.GLBegin(GL.GL_LINES);
            for (int i = 0; i < res.Length; i++)
            {
                int index = (i + 1) % 3;
                g.GLLine(res[i][0], height - res[i][1], res[index][0], height
                        - res[index][1]);
            }
            g.GLEnd();
        }

        public void DrawPaint(GLEx g, float x, float y)
        {
            Next();
            float[][] res = Drawing(x, y);
            float[] xs = new float[3];
            float[] ys = new float[3];
            int size = res.Length;
            for (int i = 0; i < size; i++)
            {
                xs[i] = res[i][0];
                ys[i] = height - res[i][1];
            }
            g.FillPolygon(xs, ys, 3);
        }

        private float GetLine(float x, float y)
        {
            return MathUtils.Sqrt(MathUtils.Pow(MathUtils.Abs(x), 2f)
                    + MathUtils.Pow(MathUtils.Abs(y), 2f));
        }

        public static float GetDegrees(float r1, float r2)
        {
            if (r1 == 0.0f && r2 == 0.0f)
            {
                return 0.0f;
            }
            float d2 = MathUtils
                    .Sqrt(MathUtils.Pow(r1, 2f) + MathUtils.Pow(r2, 2f));
            float d3 = MathUtils.ToDegrees(MathUtils.Acos(r1 / d2));
            if (MathUtils.Asin(r2 / d2) < 0.0f)
            {
                return 360f - d3;
            }
            else
            {
                return d3;
            }
        }

    }
}
